package utils

/*
 +----------------------------------------------------------------------
 + Title        : NacosRegisterServer
 + Author       : huwl
 + Version      : 1.0.0
 + Initial-Time : 2022-01-06
 + Last-time    : 这个文件最后修改的时间 + 修改人的名称
 + Desc         : nacos 服务注册与发现
 +				: 文档地址: https://github.com/nacos-group/nacos-sdk-go/blob/master/README_CN.md
 +				: 插件:
 +				: 		github.com/nacos-group/nacos-sdk-go/clients
 +				: 		github.com/nacos-group/nacos-sdk-go/common/constant
 +				: 		github.com/nacos-group/nacos-sdk-go/vo
 +----------------------------------------------------------------------
*/
import (
	"strconv"

	"github.com/nacos-group/nacos-sdk-go/clients"
	"github.com/nacos-group/nacos-sdk-go/clients/naming_client"
	"github.com/nacos-group/nacos-sdk-go/common/constant"
	"github.com/nacos-group/nacos-sdk-go/model"
	"github.com/nacos-group/nacos-sdk-go/vo"
)

/**
 * 初始化 naocs 服务及连接配置
 *
 * @params params map[string]interface{}
 * @author huwl
 * @date 2025/08/01 12:56:01
 */
func InitNacosServerAndClientConfigs(nacosCfg NacosConfig) {
	// 判断是否已经创建
	if len(NacosServerConfigs) > 0 {
		return
	}

	// 创建clientConfig
	// TimeoutMs            uint64 // 请求Nacos服务端的超时时间，默认是10000ms
	// NamespaceId          string // ACM的命名空间Id
	// Endpoint             string // 当使用ACM时，需要该配置. https://help.aliyun.com/document_detail/130146.html
	// RegionId             string // ACM&KMS的regionId，用于配置中心的鉴权
	// AccessKey            string // ACM&KMS的AccessKey，用于配置中心的鉴权
	// SecretKey            string // ACM&KMS的SecretKey，用于配置中心的鉴权
	// OpenKMS              bool   // 是否开启kms，默认不开启，kms可以参考文档 https://help.aliyun.com/product/28933.html
	//                             // 同时DataId必须以"cipher-"作为前缀才会启动加解密逻辑
	// CacheDir             string // 缓存service信息的目录，默认是当前运行目录
	// UpdateThreadNum      int    // 监听service变化的并发数，默认20
	// NotLoadCacheAtStart  bool   // 在启动的时候不读取缓存在CacheDir的service信息
	// UpdateCacheWhenEmpty bool   // 当service返回的实例列表为空时，不更新缓存，用于推空保护
	// Username             string // Nacos服务端的API鉴权Username
	// Password             string // Nacos服务端的API鉴权Password
	// LogDir               string // 日志存储路径
	// RotateTime           string // 日志轮转周期，比如：30m, 1h, 24h, 默认是24h
	// MaxAge               int64  // 日志最大文件数，默认3
	// LogLevel             string // 日志默认级别，值必须是：debug,info,warn,error，默认值是info
	NacosClientConfig = constant.ClientConfig{
		NamespaceId: nacosCfg.NameSpaceId,
		Username:    nacosCfg.Username,
		Password:    nacosCfg.Password,
		// TimeoutMs:           uint64(nacosCfg.TimeoutMs),
		// NotLoadCacheAtStart: nacosCfg.NotLoadCacheAtAtart,
		// LogDir:              nacosCfg.LogDir,
		// CacheDir:            nacosCfg.CacheDir,
		// LogLevel:            nacosCfg.LogLevel,
	}

	// 创建nacos serverConfig
	addrs := StringSplit(nacosCfg.Addrs, ",")
	for _, addr := range addrs {
		// ContextPath string // Nacos的ContextPath，默认/nacos，在2.0中不需要设置
		// IpAddr      string // Nacos的服务地址
		// Port        uint64 // Nacos的服务端口
		// Scheme      string // Nacos的服务地址前缀，默认http，在2.0中不需要设置
		// GrpcPort    uint64 // Nacos的 grpc 服务端口, 默认为 服务端口+1000, 不是必填
		ipAddr := StringSplit(addr, ":")[0]
		port, _ := strconv.ParseUint(StringSplit(addr, ":")[1], 10, 64)
		NacosServerConfigs = append(NacosServerConfigs, constant.ServerConfig{
			IpAddr:      ipAddr,
			ContextPath: nacosCfg.ContextPath,
			Port:        port,
			Scheme:      "http",
		})
	}
}

// 定义NACOS服务注册与发现结构体
type NacosServiceRegisterAndDiscovery struct {
	namingClient naming_client.INamingClient
}

/**
 * 创建NACOS服务注册
 *
 * @return *NacosServiceRegisterAndDiscovery, error
 * @author huwl
 */
func NewNacosServiceRegister() (*NacosServiceRegisterAndDiscovery, error) {
	// 创建服务发现客户端的
	namingClient, err := clients.NewNamingClient(
		vo.NacosClientParam{
			ClientConfig:  &NacosClientConfig,
			ServerConfigs: NacosServerConfigs,
		},
	)
	if err != nil {
		return nil, err
	}

	return &NacosServiceRegisterAndDiscovery{
		namingClient: namingClient,
	}, nil
}

/**
 * 创建NACOS服务发现
 *
 * @return *NacosServiceRegisterAndDiscovery, error
 * @author huwl
 */
func NewNacosServiceDiscovery() (*NacosServiceRegisterAndDiscovery, error) {
	// 创建服务发现客户端的
	namingClient, err := clients.NewNamingClient(
		vo.NacosClientParam{
			ClientConfig:  &NacosClientConfig,
			ServerConfigs: NacosServerConfigs,
		},
	)
	if err != nil {
		return nil, err
	}

	return &NacosServiceRegisterAndDiscovery{
		namingClient: namingClient,
	}, nil
}

/**
 * 注册服务
 *
 * @param string serviceHost ------------------------------------------必传
 * @param uint64 servicePort ------------------------------------------必传
 * @param string serviceName ------------------------------------------必传
 * @param string clusterName ------------------------------------------必传
 * @param string groupName --------------------------------------------必传
 * @return bool, error
 * @author huwl
 */
func (sr *NacosServiceRegisterAndDiscovery) RegisterService(serviceHost string, servicePort uint64, serviceName, clusterName, groupName string) (bool, error) {
	// 注册实例
	return sr.namingClient.RegisterInstance(vo.RegisterInstanceParam{
		Ip:          serviceHost,
		Port:        servicePort,
		ServiceName: serviceName,
		Weight:      1,
		Enable:      true,
		Healthy:     true,
		Ephemeral:   true,
		Metadata:    map[string]string{"idc": "shanghai"},
		ClusterName: clusterName, // 默认值: DEFAULT
		GroupName:   groupName,   // 默认值: DEFAULT_GROUP
	})
}

/**
 * 注销服务
 *
 * @param string serviceHost ------------------------------------------必传
 * @param uint64 servicePort ------------------------------------------必传
 * @param string serviceName ------------------------------------------必传
 * @param string clusterName ------------------------------------------必传
 * @param string groupName --------------------------------------------必传
 * @return bool, error
 * @author huwl
 */
func (sr *NacosServiceRegisterAndDiscovery) NacosDeregisterInstance(serviceHost string, servicePort uint64, serviceName, clusterName, groupName string) (bool, error) {
	return sr.namingClient.DeregisterInstance(vo.DeregisterInstanceParam{
		Ip:          serviceHost,
		Port:        servicePort,
		ServiceName: serviceName,
		Ephemeral:   true,
		Cluster:     clusterName, // 默认值DEFAULT
		GroupName:   groupName,   // 默认值DEFAULT_GROUP
	})
}

/**
 * 获取一个健康的实例（加权随机轮询）
 * SelectOneHealthyInstance将会按加权随机轮询的负载均衡策略返回一个健康的实例
 * 实例必须满足的条件：health=true,enable=true and weight>0
 *
 * @param string serviceName ------------------------------------------必传
 * @param string groupName --------------------------------------------必传
 * @param []string clusters -------------------------------------------必传
 * @return *model.Instance error
 * @author huwl
 */
func (sr *NacosServiceRegisterAndDiscovery) NacosSelectOneHealthyInstance(serviceName, groupName string, clusters []string) (*model.Instance, error) {
	return sr.namingClient.SelectOneHealthyInstance(vo.SelectOneHealthInstanceParam{
		ServiceName: serviceName,
		// GroupName:   "group-a",             // 默认值:DEFAULT_GROUP
		GroupName: groupName, // 默认值DEFAULT_GROUP
		// Clusters:    []string{"cluster-a"}, // 默认值:DEFAULT
		Clusters: clusters, // 默认值:DEFAULT
	})
}

/**
 * 获取服务信息
 *
 * @param string serviceName ------------------------------------------必传
 * @param string groupName --------------------------------------------必传
 * @param []string clusters -------------------------------------------必传
 * @return model.Service error
 * @author huwl
 */
func (sr *NacosServiceRegisterAndDiscovery) NacosGetService(serviceName, groupName string, clusters []string) (model.Service, error) {
	return sr.namingClient.GetService(vo.GetServiceParam{
		ServiceName: serviceName,
		// Clusters:    []string{"cluster-a"}, // 默认值DEFAULT
		// GroupName:   "group-a",             // 默认值DEFAULT_GROUP
		GroupName: groupName, // 默认值DEFAULT_GROUP
		Clusters:  clusters,  // 默认值DEFAULT
	})
}

/**
 * 获取所有的实例列表
 *
 * @param string serviceName ------------------------------------------必传
 * @param string groupName --------------------------------------------必传
 * @param []string clusters -------------------------------------------必传
 * @return []model.Instance error
 * @author huwl
 */
func (sr *NacosServiceRegisterAndDiscovery) NacosSelectAllInstances(serviceName, groupName string, clusters []string) ([]model.Instance, error) {
	return sr.namingClient.SelectAllInstances(vo.SelectAllInstancesParam{
		ServiceName: serviceName,
		// Clusters:    []string{"cluster-a"}, // 默认值DEFAULT
		// GroupName:   "group-a",             // 默认值DEFAULT_GROUP
		GroupName: groupName, // 默认值DEFAULT_GROUP
		Clusters:  clusters,  // 默认值DEFAULT
	})
}

/**
 * 获取实例列表
 *
 * @param string serviceName ------------------------------------------必传
 * @param string groupName --------------------------------------------必传
 * @param []string clusters -------------------------------------------必传
 * @return []model.Instance error
 * @author huwl
 */
func (sr *NacosServiceRegisterAndDiscovery) NacosSelectInstances(serviceName, groupName string, clusters []string) ([]model.Instance, error) {
	return sr.namingClient.SelectInstances(vo.SelectInstancesParam{
		ServiceName: serviceName,
		// Clusters:    []string{"cluster-a"}, // 默认值DEFAULT
		// GroupName:   "group-a",             // 默认值DEFAULT_GROUP
		GroupName:   groupName, // 默认值DEFAULT_GROUP
		Clusters:    clusters,  // 默认值DEFAULT
		HealthyOnly: true,
	})
}

/**
 * 获取实例列表
 *
 * @param string nameSpace --------------------------------------------必传
 * @param uint32 pageNo -----------------------------------------------必传
 * @param uint32 pageSize ---------------------------------------------必传
 * @return model.ServiceList error
 * @author huwl
 */
func (sr *NacosServiceRegisterAndDiscovery) NacosGetAllServicesInfo(nameSpace string, pageNo, pageSize uint32) (model.ServiceList, error) {
	return sr.namingClient.GetAllServicesInfo(vo.GetAllServiceInfoParam{
		NameSpace: nameSpace,
		PageNo:    pageNo,
		PageSize:  pageSize,
	})
}
